package com.lib.customedittext;

import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.utils.TextAlignment;
import ohos.app.Context;
import ohos.app.Environment;
import ohos.global.resource.*;
import java.io.*;
import java.lang.reflect.Field;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author Kailash Chouhan
 * CustomEditText
 *
 * @since 2021.07.27
 */

public class CustomEditText extends StackLayout {

    private static String TAG = CustomEditText.class.getSimpleName();
    private Component component_line;
    private Text tv_error;
    private Text tv_toggle_password;
    private TextField editText;
    private Image img_left;
    float defaultLabelSize;
    private int inputType;
    private static final int DEFAULT_BORDER_COLOR = Color.BLACK.getValue();
    private Element indicatorBackgroundResId=null;
    private Element drawableId = null;
    private Element cursorDrawable = null;
    private String hintText;
    private int textColor = DEFAULT_BORDER_COLOR;
    private int toggleTextColor = DEFAULT_BORDER_COLOR;
    private int textHintColor = 0;
    private int bgTintColor = 0;
    private int imageColor = 0;
    private int maxLines;
    private int maxLength;
    private int lines;
    private int gravity;
    private int mTextSize;
    private boolean isEditable = true;
    private int imeOptions;
    private int padding;
    private int padding_start;
    private int padding_end;
    private int padding_top;
    private int padding_bottom;

    /**
     * CustomEditText instance
     *
     * @param context 上下文
     */
    public CustomEditText(Context context) {
        this(context, null);
    }

    /**
     * CustomEditText instance
     *
     * @param context 上下文
     * @param attrs 属性
     */
    public CustomEditText(Context context,  AttrSet attrs) {
        this(context, attrs, "");
    }

    /**
     * CustomEditText instance
     *
     * @param context 上下文
     * @param attrs 属性
     * @param styleName 样式名称
     */
    public CustomEditText(Context context,  AttrSet attrs, String styleName) {
        super(context, attrs, styleName);

        Component view = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_widget_phone_layout, null, false);
        component_line = (Component) view.findComponentById(ResourceTable.Id_line);
        tv_error = (Text) view.findComponentById(ResourceTable.Id_tv_error);
        tv_error.setVisibility(HIDE);
        tv_toggle_password = (Text) view.findComponentById(ResourceTable.Id_tv_toggle_password);
        tv_toggle_password.setVisibility(HIDE);
        tv_toggle_password.setClickedListener(new ClickedListener() {
            @Override
            public void onClick(Component component) {
                togglePassword();
            }
        });

        img_left = (Image) view.findComponentById(ResourceTable.Id_img_left);
        img_left.setVisibility(HIDE);
        editText = (TextField) view.findComponentById(ResourceTable.Id_edt_phone);
        ShapeElement shapeElement1 = new ShapeElement();
        shapeElement1.setRgbColor(RgbColor.fromArgbInt(ResourceTable.Color_transparent));
        editText.setBubbleElement(shapeElement1);
        editText.setCursorElement(shapeElement1);
        try {
       defaultLabelSize = getResourceManager().getElement(ResourceTable.Float__15fp).getFloat();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NotExistException e) {
            e.printStackTrace();
        } catch (WrongTypeException e) {
            e.printStackTrace();
        }
        if(attrs!=null){
            mTextSize = DimensionsUtils.getDimension(attrs,"edt_text_size",
                    DimensionsUtils.getDimensionPixelSize(context, 15));
            ShapeElement shapeElement = new ShapeElement();
            shapeElement.setRgbColor(new RgbColor(255,255,0));
            indicatorBackgroundResId = DimensionsUtils.getBackgroundAttr(attrs,"edt_background",null);
            hintText =  DimensionsUtils.getStringFromAttr(attrs,"edt_hint",null);
            textColor=DimensionsUtils.getColorFromAttr(attrs,"edt_text_color",DEFAULT_BORDER_COLOR);
            toggleTextColor=DimensionsUtils.getColorFromAttr(attrs,"edt_toggle_text_color",DEFAULT_BORDER_COLOR);
            textHintColor=DimensionsUtils.getColorFromAttr(attrs,"edt_text_hint_color",0);
            bgTintColor=DimensionsUtils.getColorFromAttr(attrs,"edt_background_tint",0);
            isEditable =DimensionsUtils.getBooleanFromAttr(attrs,"edt_editable",true);
            maxLength =DimensionsUtils.getIntegerFromAttr(attrs,"edt_maxLength",10000);
            maxLines =DimensionsUtils.getIntegerFromAttr(attrs,"edt_maxLines",100);
            imeOptions =DimensionsUtils.getIntegerFromAttr(attrs,"edt_imeOptions",0);
            inputType =DimensionsUtils.getIntegerFromAttr(attrs,"edt_inputType", InputAttribute.PATTERN_TEXT);
            lines = DimensionsUtils.getIntegerFromAttr(attrs,"edt_lines",1);
            gravity =  DimensionsUtils.getIntegerFromAttr(attrs,"edt_gravity",TextAlignment.START);
            boolean togglePassword = DimensionsUtils.getBooleanFromAttr(attrs,"edt_password_toggle", false);
            padding =  DimensionsUtils.getDimension(attrs,"edt_padding",0);
            padding_start =  DimensionsUtils.getDimension(attrs,"edt_padding_start",0);
            padding_end =  DimensionsUtils.getDimension(attrs,"edt_padding_end",0);
            padding_top =  DimensionsUtils.getDimension(attrs,"edt_padding_top",0);
            padding_bottom =  DimensionsUtils.getDimension(attrs,"edt_padding_bottom",0);
            cursorDrawable =  DimensionsUtils.getBackgroundAttr(attrs,"edt_cursor",null);
            imageColor = DimensionsUtils.getColorFromAttr(attrs,"edt_image_tint",DEFAULT_BORDER_COLOR);
            if (togglePassword) {
                showPasswordToggle();
            }
            drawableId =  DimensionsUtils.getBackgroundAttr(attrs,"edt_drawable_start",null);
            boolean displayStartDrawable =DimensionsUtils.getBooleanFromAttr(attrs,"edt_show_drawable",false);
            if (displayStartDrawable) {
                showDrawable();
            }
        }

        initView();
        addComponent(view,new ComponentContainer.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT));
    }

    private void initView() {
        if (indicatorBackgroundResId != null) {
            editText.setBackground(indicatorBackgroundResId);
        }
        editText.setHint(hintText);
        editText.setTextColor(new Color(textColor));
        if (textHintColor != 0) {
            editText.setHintColor(new Color(textHintColor));
        }
        if (bgTintColor != 0) {
            component_line.setVisibility(VISIBLE);
            editText.setFocusChangedListener(new FocusChangedListener() {
                @Override
                public void onFocusChange(Component component, boolean b) {
                    if(b){
                        ComponentContainer.LayoutConfig layoutConfig = component_line.getLayoutConfig();
                        layoutConfig.height = 6;
                        component_line.setLayoutConfig(layoutConfig);
                    }else{
                        ComponentContainer.LayoutConfig layoutConfig = component_line.getLayoutConfig();
                        layoutConfig.height = 2;
                        component_line.setLayoutConfig(layoutConfig);
                    }
                }
            });
        }else{
            component_line.setVisibility(HIDE);
        }
        editText.setTextSize(mTextSize);
        editText.setMaxTextLines(lines);
        editText.setTextAlignment(gravity);
        if (padding != 0) {
            setPadding(padding);
        } else {
            setPadding(padding_start, padding_top, padding_end, padding_bottom);
        }
        if (cursorDrawable != null) {
            try {
                Field f = Text.class.getDeclaredField("mCursorDrawableRes");
                f.setAccessible(true);
                f.set(editText, cursorDrawable);
            } catch (Exception ignored) {
                Logger.getLogger("TAG").log(Level.INFO,"异常:"+ignored);
            }
        }
        tv_toggle_password.setTextColor(new Color(toggleTextColor));
        setInputType(inputType);
        setImeOptions(imeOptions);
        setEditable(isEditable);
        setMaxLines(maxLines);
        setMaxLength(maxLength);
    }

    private Font get(Context context, String assetPath) {
        ResourceManager resManager = context.getResourceManager();
        RawFileEntry rawFileEntry = resManager.getRawFileEntry(assetPath);
        Resource resource = null;
        try {
            resource = rawFileEntry.openRawFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        StringBuffer fileName = new StringBuffer(assetPath);
        File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), fileName.toString());
        OutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(file);
            int index;
            byte[] bytes = new byte[1024];
            while ((index = resource.read(bytes)) != -1) {
                outputStream .write(bytes, 0, index);
                outputStream .flush();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                resource.close();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        Font.Builder builder = new Font.Builder(file);
        return builder.build();
    }

    /**
     * setTypeface
     *
     * @param font 字体
     */
    public void setTypeface(Font font) {
        editText.setFont(font);
        tv_toggle_password.setFont(font);
        tv_error.setFont(font);
    }

    /**
     * setMaxLength
     *
     * @param maxLength 最长长度
     */
    public void setMaxLength(int maxLength) {
        editText.addTextObserver(new Text.TextObserver() {
            @Override
            public void onTextUpdated(String s0, int i, int i1, int i2) {
                if(s0.length()<maxLength){
                    editText.setText(s0);
                }
            }
        });
    }

    /**
     * setBackground
     *
     * @param drawable 背景元素
     */
    public void setBackground(Element drawable) {
        editText.setBackground(drawable);
    }

    /**
     * setTextColor
     *
     * @param color 字体颜色
     */
    public void setTextColor(Color color) {
        editText.setTextColor(color);
    }

    /**
     * setSelection
     *
     */
    public void setSelection() {

    }

    /**
     * setTextSize
     *
     * @param textSize 字体大小
     */
    public void setTextSize(int textSize) {
        editText.setTextSize(textSize, Text.TextSizeType.FP);
    }

    /**
     * setInputType
     *
     * @param inputType 输入类型
     */
    public void setInputType(int inputType) {
        editText.setTextInputType(inputType);
    }

    /**
     * showDrawable
     *
     */
    public void showDrawable() {
        img_left.setVisibility(VISIBLE);
        img_left.setImageElement(drawableId);
    }

    /**
     * showPasswordToggle
     *
     */
    public void showPasswordToggle() {
        tv_toggle_password.setVisibility(VISIBLE);
        tv_toggle_password.setSelected(true);
    }

    /**
     * setEditable
     *
     * @param isEditable boolean
     */
    public void setEditable(boolean isEditable) {
        editText.setFocusable(isEditable?Component.FOCUS_ADAPTABLE:Component.FOCUS_DISABLE);
        editText.setTouchFocusable(isEditable);
    }

    /**
     * togglePassword
     *
     */
    public void togglePassword() {
        if (tv_toggle_password.isSelected()) {
            tv_toggle_password.setSelected(false);
            try {
                tv_toggle_password.setText(getContext().getResourceManager().getElement(ResourceTable.String_label_hide).getString());
            } catch (IOException e) {
                e.printStackTrace();
            } catch (NotExistException e) {
                e.printStackTrace();
            } catch (WrongTypeException e) {
                e.printStackTrace();
            }
            editText.setTextInputType(InputAttribute.PATTERN_TEXT);
        } else {
            tv_toggle_password.setSelected(true);

            try {
                tv_toggle_password.setText(getContext().getResourceManager().getElement(ResourceTable.String_label_show).getString());
            } catch (IOException e) {
                e.printStackTrace();
            } catch (NotExistException e) {
                e.printStackTrace();
            } catch (WrongTypeException e) {
                e.printStackTrace();
            }
            editText.setTextInputType(InputAttribute.PATTERN_PASSWORD);
        }
        setSelection();
    }

    /**
     * setPadding
     *
     * @param padding 填充
     */
    public void setPadding(int padding) {
        setPadding(padding, padding, padding, padding);
    }

    /**
     * setPadding
     *
     * @param left left
     * @param top top
     * @param right right
     * @param bottom bottom
     */
    public void setPadding(int left, int top, int right, int bottom) {
        editText.setPadding(left, top, right, bottom);
    }

    /**
     * getHintTextView
     *
     * @return tv_error
     */
    public Text getHintTextView() {
        return tv_error;
    }

    /**
     * getEditText
     *
     * @return editText
     */
    public TextField getEditText() {
        return editText;
    }

    /**
     * setText
     *
     * @param charSequence charSequence
     */
    public void setText(CharSequence charSequence) {
        editText.setText(charSequence.toString());
    }

    /**
     * getText
     *
     * @return editText
     */
    public String getText() {
        return editText.getText().toString().trim();
    }

    /**
     * setErrorEnabled
     *
     * @param isErrorEnable
     */
    public void setErrorEnabled(boolean isErrorEnable) {
        tv_error.setVisibility(isErrorEnable ? VISIBLE : HIDE);
    }

    /**
     * setError
     *
     * @param errorText
     */
    public void setError(String errorText) {
        if (isNullOrEmpty(errorText)) {
            tv_error.setVisibility(HIDE);
        } else {
            tv_error.setVisibility(VISIBLE);
            tv_error.setText(errorText);
        }
    }

    /**
     * setCompoundDrawablesWithIntrinsicBounds
     *
     * @param i0 Element
     * @param i1 Element
     * @param i2 Element
     * @param i3 Element
     */
    public void setCompoundDrawablesWithIntrinsicBounds(Element i0, Element i1, Element i2, Element i3) {
        editText.setAroundElements(i0, i1, i2, i3);
    }

    /**
     * clearText
     *
     */
    public void clearText() {
        editText.setText("");
    }

    /**
     * setErrorPadding
     *
     * @param left left
     * @param top top
     * @param right right
     * @param bottom bottom
     */
    public void setErrorPadding(int left, int top, int right, int bottom) {
        tv_error.setPadding(left, top, right, bottom);
    }


    /**
     * Change the editor type integer associated with the text view, which
     * is reported to an Input Method Editor (IME) with when it has focus.
     *
     * setImeOptions
     *
     * @param imeOptions imeOptions
     */
    public void setImeOptions(int imeOptions) {
        editText.setInputMethodOption(imeOptions);
    }

    /**
     * setOnClickListener
     *
     * @param listener 监听
     */
    public void setOnClickListener(final ClickedListener listener) {
        editText.setClickedListener(new ClickedListener() {
            @Override
            public void onClick(Component component) {
                listener.onClick(component);
            }
        });

    }

    /**
     * Sets the text to be displayed when the text of the TextView is empty.
     * Null means to use the normal empty text. The hint does not currently
     * participate in determining the size of the view.
     *
     * setHint
     *
     * @param hint hint
     */
    public final void setHint(String hint) {
        editText.setHint(hint);
    }

    /**
     * setHint
     *
     * @param hint hint
     */
    public final void setHint(StringBuilder hint) {
        editText.setHint(hint.toString());
    }

    /**
     * Sets the text to be displayed when the text of the TextView is empty,
     * from a resource.
     *
     * setHint
     *
     * @param resid
     * @throws IOException NotExistException WrongTypeException
     *
     */
    public final void setHint(int resid) {
        try {
            setHint(getContext().getResourceManager().getElement(resid).getString());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NotExistException e) {
            e.printStackTrace();
        } catch (WrongTypeException e) {
            e.printStackTrace();
        }
    }

    /**
     * setOnEditorActionListener
     *
     * @param listener 监听
     */
    public void setOnEditorActionListener( Text.EditorActionListener listener) {
        editText.setEditorActionListener(new Text.EditorActionListener() {
            @Override
            public boolean onTextEditorAction(int i1) {
                listener.onTextEditorAction(i1);
                return false;
            }
        });
    }

    /**
     * setLines
     *
     * @param lines lines
     */
    public void setLines(int lines) {
        editText.setMultipleLine(true);
        editText.setMaxTextLines(lines);
    }

    /**
     * setMaxLines
     *
     * @param maxLines maxLines
     */
    public void setMaxLines(int maxLines) {
        editText.setMaxTextLines(maxLines);
    }

    /**
     * setGravity
     *
     * @param gravity gravity
     */
    public void setGravity(int gravity) {
        editText.setTextAlignment(gravity);
    }

    /**
     * isNullOrEmpty
     *
     * @param s1 String
     * @return s1
     */
    public static boolean isNullOrEmpty(String s1) {
        if (s1 == null)
            return true;
        if (s1.length() == 0)
            return true;
        return s1.equalsIgnoreCase("null");
    }

}
